/** @file GameAPI.cpp */

#include "LuaContext.h"
#include "MainLoop.h"
#include "Game.h"
#include "Savegame.h"
#include "FileTools.h"
#include "lua.hpp"

const std::string LuaContext::game_module_name = "kq.game";

/**
 * \brief Initializes the game features provided to lua.
 */
void LuaContext::register_game_module()
{
	static const luaL_Reg methods[] = 
	{
      { "exists", game_api_exists },
      { "delete", game_api_delete },
      { "load", game_api_load },
      { "save", game_api_save },
      { "start", game_api_start },
      { "is_started", game_api_is_started },
      { "is_suspended", game_api_is_suspended },
      { "is_paused", game_api_is_paused },
      { "set_paused", game_api_set_paused },
      { "get_map", game_api_get_map },
      { "get_value", game_api_get_value },
      { "set_value", game_api_set_value },
      { "get_starting_location", game_api_get_starting_location },
      { "set_starting_location", game_api_set_starting_location },
      { "get_life", game_api_get_life },
      { "set_life", game_api_set_life },
      { "add_life", game_api_add_life },
      { "remove_life", game_api_remove_life },
      { "get_max_life", game_api_get_max_life },
      { "set_max_life", game_api_set_max_life },
      { "add_max_life", game_api_add_max_life },
      { "get_money", game_api_get_money },
      { "set_money", game_api_set_money },
      { "add_money", game_api_add_money },
      { "remove_money", game_api_remove_money },
      { "get_max_money", game_api_get_max_money },
      { "set_max_money", game_api_set_max_money },
      { "get_magic", game_api_get_magic},
      { "set_magic", game_api_set_magic},
      { "add_magic", game_api_add_magic},
      { "remove_magic", game_api_remove_magic},
      { "get_max_magic", game_api_get_max_magic},
      { "set_max_magic", game_api_set_max_magic},
      { "has_ability", game_api_has_ability },
      { "get_ability", game_api_get_ability },
      { "set_ability", game_api_set_ability },
      { "get_item", game_api_get_item },
      { "has_item", game_api_has_item },
      { "get_item_assigned", game_api_get_item_assigned },
      { "set_item_assigned", game_api_set_item_assigned },
      { "is_command_pressed", game_api_is_command_pressed },
      { "get_commands_direction", game_api_get_commands_direction },
      { "get_command_effect", game_api_get_command_effect },
      { "get_command_keyboard_binding", game_api_get_command_keyboard_binding },
      { "set_command_keyboard_binding", game_api_set_command_keyboard_binding },
      { "get_command_joypad_binding", game_api_get_command_joypad_binding },
      { "set_command_joypad_binding", game_api_set_command_joypad_binding },
      { "capture_command_binding", game_api_capture_command_binding },
      { NULL, NULL }
  };
  static const luaL_Reg metamethods[] =
  {
	{ "__gc", userdata_meta_gc },
    { "__newindex", userdata_meta_newindex_as_table },
    { "__index", userdata_meta_index_as_table },
    { NULL, NULL }
  };
  register_type(game_module_name, methods, metamethods);
}

/**
* \brief Returns whether a value is a userdata of type game.
* \param l A Lua context.
* \param index An index in the stack.
* \return true if the value at this index is a game.
*/
bool LuaContext::is_game(lua_State* l, int index) 
{
  return is_userdata(l, index, game_module_name);
}

/**
* \brief Checks that the userdata at the specified index of the stack is a
* game and returns it.
* \param l a Lua context
* \param index an index in the stack
* \return the game
*/
Savegame& LuaContext::check_game(lua_State* l, int index) 
{
  return static_cast<Savegame&>(check_userdata(l, index, game_module_name));
}

/**
* \brief Pushes a game userdata onto the stack.
* \param l A Lua context.
* \param game A game.
*/
void LuaContext::push_game(lua_State* l, Savegame& game) 
{
  push_userdata(l, game);
}

/**
* \brief Implementation of game:start().
* \param l The Lua context that is calling this function.
* \return Number of values to return to Lua.
*/
int LuaContext::game_api_start(lua_State* l)
{
	Savegame& savegame = check_game(l, 1);
	
	Game* game = savegame.get_game();
	if(game != NULL)
	{
		//A game is already running with this savegame: restart it.
		game->restart();
	}
	else
	{
		//Create a new game to run
		MainLoop& main_loop = savegame.get_lua_context().get_main_loop();
		Game* game = new Game(main_loop, &savegame);
		main_loop.set_game(game);
	}
	return 0;
}

